import json
import datetime
from django.shortcuts import render
from django.http import JsonResponse
from django.urls import reverse
from django.views.decorators.csrf import csrf_exempt
from django.utils.safestring import mark_safe

from web.forms.issues import IssuesModelForm, IssuesReplyModelForm, InviteForm
from web import models
from untils.pagination import Pagination
from untils import encrypt


class CheckFilter(object):
    def __init__(self, data_list, request, name):
        self.data_list = data_list
        self.request = request
        self.name = name

    def __iter__(self):
        for item in self.data_list:
            key = str(item[0])
            value = item[1]
            ck = ""
            # 判断当前用户请求的URL中的数据是否与上面的数据对应
            value_list = self.request.GET.getlist(self.name)
            if key in value_list:
                ck = "checked"
                value_list.remove(key)
            else:
                value_list.append(key)

            # 为自己生成URL
            # 在当前URL的基础上去增加一项
            query_dict = self.request.GET.copy()
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)

            if 'page' in query_dict:
                query_dict.pop('page')

            url = f"{self.request.path_info}?{query_dict.urlencode()}"

            html = f"<a class='cell' href='{url}'><input type='checkbox' {ck} /><label>{value}</label></a>"
            yield mark_safe(html)


class SelectFilter(object):
    def __init__(self, data_list, request, name):
        self.data_list = data_list
        self.request = request
        self.name = name

    def __iter__(self):
        yield mark_safe("<select class='select2' multiple='multiple' style='width:100% '>")
        for item in self.data_list:
            key = str(item[0])
            value = item[1]
            selected = ""
            value_list = self.request.GET.getlist(self.name)
            if key in value_list:
                selected = "selected"
                value_list.remove(key)
            else:
                value_list.append(key)

            # 为自己生成URL
            # 在当前URL的基础上去增加一项
            query_dict = self.request.GET.copy()
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)

            if 'page' in query_dict:
                query_dict.pop('page')

            url = f"{self.request.path_info}?{query_dict.urlencode()}"
            yield mark_safe(f"<option value='{url}' {selected} >{value}</option>")

        yield mark_safe("</select>")


def issues(request, project_id):
    if request.method == 'GET':

        # 根据URL做筛选

        allow_filter_name = ['issues_type', 'status', 'priority', 'assign', 'attention']
        condition = {}
        for name in allow_filter_name:
            value_list = request.GET.getlist(name)
            if not value_list:
                continue
            # 这里的加__in是为了找该字段中是这个列表的值
            # 找age是12,14,42的值
            # 例:res = models.Student.objects.filter(age__in=[12, 14, 42]).all()
            condition[f'{name}__in'] = value_list

        # 分页
        #     1.页面显示数据处理
        queryset = models.Issues.objects.filter(project_id=project_id).filter(**condition)

        page_object = Pagination(
            current_page=request.GET.get('page'),
            all_count=queryset.count(),  # 获取要分页的数据数量
            base_url=request.path_info,
            query_params=request.GET,
            per_page=5,  # 设置一页几条数据
        )
        issues_object_list = queryset[page_object.start:page_object.end]
        #      2.页面页码显示处理
        page_html = page_object.page_html()

        # 模态框表单
        form = IssuesModelForm(request)
        # 该项目的数据
        issues_list = models.Issues.objects.filter(project_id=project_id)
        project_issues_type_list = models.IssuesType.objects.filter(project_id=project_id).values_list('id', 'title')

        project_total_user = [(request.tracer.project.creator.id, request.tracer.project.creator.username), ]
        project_join_user = models.ProjectUser.objects.filter(project_id=project_id).values_list('user_id',
                                                                                                 'user__username')

        project_total_user.extend(project_join_user)

        invite_form = InviteForm()

        return render(request,
                      'issues.html',
                      {'form': form,
                       'invite_form': invite_form,
                       'issues_list': issues_list,
                       'issues_object_list': issues_object_list,
                       'page_html': page_html,
                       'filter_list': [
                           {'title': '问题类型', 'filter': CheckFilter(project_issues_type_list, request, 'issues_type')},
                           {'title': '优先级', 'filter': CheckFilter(models.Issues.priority_choices, request, 'priority')},
                           {'title': '状态', 'filter': CheckFilter(models.Issues.status_choices, request, 'status')},
                           {'title': '指派者', 'filter': SelectFilter(project_total_user, request, 'assign')},
                           {'title': '关注者', 'filter': SelectFilter(project_total_user, request, 'attention')},
                       ]
                       })

    form = IssuesModelForm(request, data=request.POST)
    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        form.save()

        return JsonResponse({'status': True})
    return JsonResponse({'status': False, 'errors': form.errors})


def issues_detail(request, project_id, issues_id):
    issues_obj = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    form = IssuesModelForm(request, instance=issues_obj)
    return render(request, 'issues_detail.html', {'form': form, 'issues_obj': issues_obj})


@csrf_exempt
def issues_record(request, project_id, issues_id):
    """ 初始化操作记录 """
    if request.method == 'GET':
        reply_list = models.IssuesReply.objects.filter(issues_id=issues_id, issues__project=request.tracer.project)
        # 将queryset转换为json格式
        data_list = []
        for row in reply_list:
            data = {
                'id': row.id,
                'reply_type_text': row.get_reply_type_display(),
                'content': row.content,
                'creator': row.creator.username,
                'datetime': row.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': row.reply_id
            }
            data_list.append(data)

        return JsonResponse({'status': True, 'data': data_list})

    form = IssuesReplyModelForm(data=request.POST)
    if form.is_valid():
        form.instance.issues_id = issues_id
        form.instance.reply_type = 2
        form.instance.creator = request.tracer.user
        instance = form.save()
        info = {
            'id': instance.id,
            'reply_type_text': instance.get_reply_type_display(),
            'content': instance.content,
            'creator': instance.creator.username,
            'datetime': instance.create_datetime.strftime("%Y-%m-%d %H:%M"),
            'parent_id': instance.reply_id
        }

        return JsonResponse({'status': True, 'data': info})
    return JsonResponse({'status': False, 'error': form.errors})


@csrf_exempt
def issues_change(request, project_id, issues_id):
    post_dict = json.loads(request.body.decode('utf-8'))
    name = post_dict['name']
    value = post_dict['value']

    issues_obj = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    field_obj = models.Issues._meta.get_field(name)

    # 如果是文本字段的修改
    if name in ["subject", "desc", "start_date", "end_date"]:
        if value:
            setattr(issues_obj, name, value)
            issues_obj.save()
            field_change_record = f"{field_obj.verbose_name} 更新为 {value}"
        else:
            if field_obj.null:
                setattr(issues_obj, name, None)
                issues_obj.save()
                field_change_record = f"{field_obj.verbose_name} 更新为 空"
            else:
                return JsonResponse({'status': False, 'error': '该字段不能为空'})

    # 如果是FK字段
    if name in ["issues_type", "module", "parent", "assign"]:
        if not value:
            if not field_obj.null:
                return JsonResponse({'status': False, 'error': '该字段不能为空'})
            else:
                setattr(issues_obj, name, None)
                issues_obj.save()
                field_change_record = f"{field_obj.verbose_name} 更新为 {value}"
        else:
            if name == 'assign':
                if value == str(request.tracer.project.creator_id):
                    instance = request.tracer.project.creator
                else:
                    project_user_object = models.ProjectUser.objects.filter(project_id=project_id,
                                                                            user_id=value).first()
                    if project_user_object:
                        instance = project_user_object.user
                    else:
                        instance = None
                if not instance:
                    return JsonResponse({'status': False, 'error': "您选择的值不存在"})
                else:
                    setattr(issues_obj, name, instance)
                    issues_obj.save()
                    field_change_record = f"{field_obj.verbose_name} 更新为 {str(instance)}"  # value根据文本获取到内容
            else:
                # 条件判断：用户输入的值，是自己的值。
                instance = field_obj.remote_field.model.objects.filter(id=value, project_id=project_id).first()

                if not instance:
                    return JsonResponse({'status': False, 'error': "您选择的值不存在"})

                setattr(issues_obj, name, instance)
                issues_obj.save()
                field_change_record = "{} 更新为 {}".format(field_obj.verbose_name, str(instance))  # value根据文本获取到内容

    # 如果是choices字段
    if name in ['priority', 'status', 'mode']:
        selected_text = None
        for key, text in field_obj.choices:
            if str(key) == value:
                selected_text = text
        if not selected_text:
            return JsonResponse({'status': False, 'error': "您选择的值不存在"})
        else:
            setattr(issues_obj, name, value)
            issues_obj.save()
            field_change_record = "{} 更新为 {}".format(field_obj.verbose_name, selected_text)

        # 1.4 M2M字段
    if name == "attention":
        # {"name":"attention","value":[1,2,3]}
        if not isinstance(value, list):
            return JsonResponse({'status': False, 'error': "数据格式错误"})

        if not value:
            issues_obj.attention.set(value)
            issues_obj.save()
            field_change_record = "{} 更新为 空".format(field_obj.verbose_name)
        else:
            # values=["1","2,3,4]  ->   id是否是项目成员（参与者、创建者）
            # 获取当前项目的所有成员
            user_dict = {str(request.tracer.project.creator_id): request.tracer.project.creator.username}
            project_user_list = models.ProjectUser.objects.filter(project_id=project_id)
            for item in project_user_list:
                user_dict[str(item.user_id)] = item.user.username
            username_list = []
            for user_id in value:
                username = user_dict.get(str(user_id))
                if not username:
                    return JsonResponse({'status': False, 'error': "用户不存在请重新设置"})
                username_list.append(username)

            issues_obj.attention.set(value)
            issues_obj.save()
            field_change_record = "{} 更新为 {}".format(field_obj.verbose_name, ",".join(username_list))

    # 为修改的字段添加一条回复信息
    field_change_reply = models.IssuesReply.objects.create(
        reply_type=1,
        issues=issues_obj,
        content=field_change_record,
        creator=request.tracer.user,
    )

    data = {
        'id': field_change_reply.id,
        'reply_type_text': field_change_reply.get_reply_type_display(),
        'content': field_change_reply.content,
        'creator': field_change_reply.creator.username,
        'datetime': field_change_reply.create_datetime.strftime("%Y-%m-%d %H:%M"),
        'parent_id': field_change_reply.reply_id
    }

    return JsonResponse({'status': True, 'data': data})


def invite_url(request, project_id):
    form = InviteForm(data=request.POST)

    if form.is_valid():
        # 判断发起邀请的用户是否是当前项目创建者
        # 如果不是
        if request.tracer.user != request.tracer.project.creator:
            form.add_error('period', "您不是当前项目创建者，权限不足")
            return JsonResponse({'status': False, 'errors': form.errors})

        # 如果是
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        # 随机生成邀请码
        code = encrypt.md5(encrypt.uuid_code(request.tracer.user.mobile_phone))
        form.instance.code = code
        form.save()

        # 在生成一个url+邀请码 /invite/join/邀请码
        url = "{scheme}://{host}{path}".format(
            scheme=request.scheme,  # 这个是获取当前url的前缀(http,https等)
            host=request.get_host(),  # 这个是获取当前url的域名与端口号
            path=reverse('invite_join', kwargs={'code': code})
        )
        return JsonResponse({'status': True, 'data': url})

    return JsonResponse({'status': False, 'errors': form.errors})


def invite_join(request, code):
    """邀请限制"""

    invite_obj = models.ProjectInvite.objects.filter(code=code).first()

    if not invite_obj:
        return render(request, 'invite.html', {'error': "邀请码不存在"})

    # 用户判断

    if request.tracer.user == invite_obj.creator:
        return render(request, 'invite.html', {'error': "创建者无需加入"})

    exists = models.ProjectUser.objects.filter(project=invite_obj.project, user=request.tracer.user).exists()
    if exists:
        return render(request, 'invite.html', {'error': "已加入该项目"})

    # 项目创建者的交易记录的价格策略
    max_transaction = models.Transaction.objects.filter(user=invite_obj.project.creator).order_by('-id').first()
    current_datetime = datetime.datetime.now()
    if max_transaction.price_policy.category == 1:
        max_member = max_transaction.price_policy.project_member
    else:
        if max_transaction.end_datetime < current_datetime:
            free_object = models.PricePolicy.objects.filter(category=1).first()
            max_member = free_object.project_member
        else:
            max_member = max_transaction.price_policy.project_member

    # 目前所有成员(创建者&参与者）
    current_member = models.ProjectUser.objects.filter(project=invite_obj.project).count()
    current_member = current_member + 1
    if current_member >= max_member:
        return render(request, 'invite.html', {'error': '项目成员超限，请升级套餐'})

    # 邀请码是否过期？
    limit_datetime = invite_obj.create_datetime + datetime.timedelta(minutes=invite_obj.period)
    if current_datetime > limit_datetime:
        return render(request, 'invite.html', {'error': '邀请码已过期'})

    # 数量限制？
    if invite_obj.count:
        if invite_obj.use_count >= invite_obj.count:
            return render(request, 'invite.html', {'error': '邀请码数据已使用完'})
        invite_obj.use_count += 1
        invite_obj.save()

    models.ProjectUser.objects.create(user=request.tracer.user, project=invite_obj.project)

    # ####### 问题2： 更新项目参与成员 #######
    invite_obj.project.join_count += 1
    invite_obj.project.save()

    return render(request, 'invite.html', {'project': invite_obj.project})
